package team.knowers.qzhserver.course.datum.datum.service.Impl;

import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import team.knowers.qzhserver.course.datum.datum.entity.dao.DatumDO;
import team.knowers.qzhserver.course.datum.datum.entity.dto.DatumUpdateDTO;
import team.knowers.qzhserver.course.datum.datum.mapper.DatumMapper;
import team.knowers.qzhserver.course.datum.datum.service.DatumCacheService;
import team.knowers.qzhserver.course.datum.datum.service.DatumService;
import team.knowers.qzhserver.course.datum.file.service.FileService;

import java.util.Date;
import java.util.List;
import java.util.Set;

@Service
public class DatumServiceImpl implements DatumService {
    @Autowired
    private DatumMapper datumMapper;
    @Override
    public DatumDO createDatum(String cid, String uid,String name) {
        DatumDO datumDO = DatumDO.builder()
                .courseId(cid)
                .userId(uid)
                .name(name)
                .gmtCreate(new Date())
                .gmtModified(new Date())
                .build();
        datumMapper.insert(datumDO);
        return datumDO;
    }

    @Override
    public DatumDO getDatumById(String id) {
        //先从缓存中查找
        DatumDO datumDO = getCacheService().getDatum(id);
        if(datumDO==null){
            //当缓存中查找不到时，去数据库中查找
            datumDO=datumMapper.selectById(id);
            if(datumDO==null)
                //依然查找不到时查找失败
                return null;
        }
        //查找到时更新缓存并返回对象
        getCacheService().setDatum(datumDO);
        getCacheService().setCourseDatumSet(datumDO.getCourseId(),datumDO.getId());
        return datumDO;
    }
    /**
     * 请记住！所有对现有对象做更新、删除操作的时候务必也对缓存中的对象一起更新和删除
     */
    @Override
    public DatumCacheService getCacheService() {
        return SpringUtil.getBean(DatumCacheService.class);
    }

    @Override
    public Boolean updateDatum(DatumUpdateDTO datumUpdateDTO) {
        DatumDO datumDO = getDatumById(datumUpdateDTO.getId());
        datumDO.setName(datumUpdateDTO.getName());
        datumDO.setStatus(datumUpdateDTO.getStatus());
        datumDO.setGmtModified(new Date());
        getCacheService().setDatum(datumDO);
        getCacheService().setCourseDatumSet(datumDO.getCourseId(),datumDO.getId());
        return datumMapper.updateById(datumDO)==1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteDatum(String id) throws Exception {
        DatumDO datumDO = getDatumById(id);
        if(datumDO==null)
            return false;
        //连锁删除资料库中的所有资料
        for(String fid:getFileService().getDatumFileSet(id)){
            getFileService().getCacheService().delFile(fid);
            if(!getFileService().deleteFile(fid)){
                throw new Exception("删除资料时发生异常");
            }
        }
        getFileService().getCacheService().delDatumFileSetAll(id);
        //删除资料库自身的数据
        getCacheService().delDatum(id);
        getCacheService().delCourseDatumSet(datumDO.getCourseId(),id);
        if (datumMapper.deleteById(datumDO)==1){
            return true;
        }else {
            throw new Exception("删除资料库时发生异常");
        }
    }

    @Override
    public Set<String> getCourseDatumSet(String cid) {
        //先从缓存中获取
        Set<String> output = getCacheService().getCourseDatumSet(cid);
        if(output.isEmpty()){
            //从缓存中获取不到时，从数据库中获取
            List<DatumDO> datumDOS = datumMapper.selectList(new QueryWrapper<DatumDO>().eq("course_id",cid));
            for(DatumDO datumDO:datumDOS){
                output.add(datumDO.getId());
            }
        }
        return output;
    }

    private FileService getFileService(){return SpringUtil.getBean(FileService.class);}
}
